import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 玩家出牌模型类
 * 
 * <p>该类用于分析和建模玩家手牌，将手牌分解为各种可能的出牌组合：
 * <ul>
 *   <li>单张</li>
 *   <li>对子</li>
 *   <li>三张</li>
 *   <li>顺子</li>
 *   <li>连对</li>
 *   <li>飞机（连续三张）</li>
 *   <li>炸弹（四张或王炸）</li>
 * </ul>
 * 
 * <p>该模型用于支持AI出牌决策和游戏策略分析。
 */
public class GameModel {
    // 牌型存储
    private List<String> singles = new ArrayList<>();      // 单张牌
    private List<String> pairs = new ArrayList<>();        // 对子牌
    private List<String> threes = new ArrayList<>();       // 三张牌
    private List<String> straights = new ArrayList<>();     // 顺子（5张或更多连续单牌）
    private List<String> consecutivePairs = new ArrayList<>(); // 连对（3对或更多连续对子）
    private List<String> airplanes = new ArrayList<>();    // 飞机（2组或更多连续三张）
    private List<String> bombs = new ArrayList<>();        // 炸弹（四张相同牌或王炸）
    
    // 牌型权重（用于评估牌力）
    private static final int SINGLE_WEIGHT = 1;
    private static final int PAIR_WEIGHT = 2;
    private static final int THREE_WEIGHT = 4;
    private static final int STRAIGHT_WEIGHT = 3;
    private static final int CONSECUTIVE_PAIR_WEIGHT = 5;
    private static final int AIRPLANE_WEIGHT = 6;
    private static final int BOMB_WEIGHT = 10;
    
    /**
     * 清空模型数据
     */
    public void clear() {
        singles.clear();
        pairs.clear();
        threes.clear();
        straights.clear();
        consecutivePairs.clear();
        airplanes.clear();
        bombs.clear();
    }
    
    // -------------------- 添加牌型的方法 --------------------
    
    /**
     * 添加单张牌
     * @param card 卡牌标识（格式："花色-点数"）
     */
    public void addSingle(String card) {
        singles.add(card);
    }
    
    /**
     * 添加一对牌
     * @param pair 对子标识（格式："花色1-点数,花色2-点数"）
     */
    public void addPair(String pair) {
        pairs.add(pair);
    }
    
    /**
     * 添加三张牌
     * @param three 三张牌标识（格式："花色1-点数,花色2-点数,花色3-点数"）
     */
    public void addThree(String three) {
        threes.add(three);
    }
    
    /**
     * 添加顺子
     * @param straight 顺子标识（格式："花色1-点数1,花色2-点数2,..."）
     */
    public void addStraight(String straight) {
        straights.add(straight);
    }
    
    /**
     * 添加连对
     * @param consecutivePair 连对标识（格式："花色1-点数,花色2-点数,花色3-点数,花色4-点数,..."）
     */
    public void addConsecutivePair(String consecutivePair) {
        consecutivePairs.add(consecutivePair);
    }
    
    /**
     * 添加飞机
     * @param airplane 飞机标识（格式："花色1-点数,花色2-点数,花色3-点数,花色4-点数,花色5-点数,花色6-点数,..."）
     */
    public void addAirplane(String airplane) {
        airplanes.add(airplane);
    }
    
    /**
     * 添加炸弹
     * @param bomb 炸弹标识（格式："花色1-点数,花色2-点数,花色3-点数,花色4-点数"）
     */
    public void addBomb(String bomb) {
        bombs.add(bomb);
    }
    
    // -------------------- 获取牌型的方法 --------------------
    
    /**
     * 获取所有单张牌
     * @return 单张牌列表
     */
    public List<String> getSingles() {
        return sortCardStrings(singles);
    }
    
    /**
     * 获取所有对子
     * @return 对子列表
     */
    public List<String> getPairs() {
        return sortCardStrings(pairs);
    }
    
    /**
     * 获取所有三张牌
     * @return 三张牌列表
     */
    public List<String> getThrees() {
        return sortCardStrings(threes);
    }
    
    /**
     * 获取所有顺子
     * @return 顺子列表
     */
    public List<String> getStraights() {
        return sortCardStrings(straights);
    }
    
    /**
     * 获取所有连对
     * @return 连对列表
     */
    public List<String> getConsecutivePairs() {
        return sortCardStrings(consecutivePairs);
    }
    
    /**
     * 获取所有飞机
     * @return 飞机列表
     */
    public List<String> getAirplanes() {
        return sortCardStrings(airplanes);
    }
    
    /**
     * 获取所有炸弹
     * @return 炸弹列表
     */
    public List<String> getBombs() {
        return sortCardStrings(bombs);
    }
    
    // -------------------- 分析牌型的方法 --------------------
    
    /**
     * 获取总牌型权重（评估手牌整体强度）
     * @return 总权重值
     */
    public int getTotalWeight() {
        int weight = 0;
        weight += singles.size() * SINGLE_WEIGHT;
        weight += pairs.size() * PAIR_WEIGHT;
        weight += threes.size() * THREE_WEIGHT;
        weight += straights.size() * STRAIGHT_WEIGHT;
        weight += consecutivePairs.size() * CONSECUTIVE_PAIR_WEIGHT;
        weight += airplanes.size() * AIRPLANE_WEIGHT;
        weight += bombs.size() * BOMB_WEIGHT;
        return weight;
    }
    
    /**
     * 获取最大可出牌型（用于AI主动出牌）
     * @return 最大牌型标识
     */
    public String getLargestPlayableSet() {
        // 优先选择炸弹
        if (!bombs.isEmpty()) {
            return getHighestCardSet(bombs);
        }
        
        // 其次选择飞机
        if (!airplanes.isEmpty()) {
            return getHighestCardSet(airplanes);
        }
        
        // 然后选择连对
        if (!consecutivePairs.isEmpty()) {
            return getHighestCardSet(consecutivePairs);
        }
        
        // 接着选择顺子
        if (!straights.isEmpty()) {
            return getHighestCardSet(straights);
        }
        
        // 再选择三张
        if (!threes.isEmpty()) {
            return getHighestCardSet(threes);
        }
        
        // 然后选择对子
        if (!pairs.isEmpty()) {
            return getHighestCardSet(pairs);
        }
        
        // 最后选择单张
        if (!singles.isEmpty()) {
            return getHighestCardSet(singles);
        }
        
        return null;
    }
    
    /**
     * 获取最小可出牌型（用于AI保守出牌）
     * @return 最小牌型标识
     */
    public String getSmallestPlayableSet() {
        // 优先选择单张
        if (!singles.isEmpty()) {
            return getLowestCardSet(singles);
        }
        
        // 其次选择对子
        if (!pairs.isEmpty()) {
            return getLowestCardSet(pairs);
        }
        
        // 然后选择三张
        if (!threes.isEmpty()) {
            return getLowestCardSet(threes);
        }
        
        // 接着选择顺子
        if (!straights.isEmpty()) {
            return getLowestCardSet(straights);
        }
        
        // 再选择连对
        if (!consecutivePairs.isEmpty()) {
            return getLowestCardSet(consecutivePairs);
        }
        
        // 最后选择飞机
        if (!airplanes.isEmpty()) {
            return getLowestCardSet(airplanes);
        }
        
        return null;
    }
    
    /**
     * 查找能压制指定牌型的组合（用于AI应对出牌）
     * @param opponentSet 对手出的牌型标识
     * @return 能压制的牌型标识，如果没有返回null
     */
    public String findCounterSet(String opponentSet) {
        // 解析对手牌型
        CardType opponentType = CommonUtils.determineCardSetType(opponentSet);
        int opponentValue = CommonUtils.getCardSetValue(opponentSet);
        
        // 根据牌型寻找压制组合
        switch (opponentType) {
            case SINGLE:
                return findHigherSingle(opponentValue);
                
            case PAIR:
                return findHigherPair(opponentValue);
                
            case THREE:
                return findHigherThree(opponentValue);
                
            case STRAIGHT:
                return findHigherStraight(opponentSet);
                
            case CONSECUTIVE_PAIRS:
                return findHigherConsecutivePairs(opponentSet);
                
            case AIRPLANE:
                return findHigherAirplane(opponentSet);
                
            case BOMB:
                return findHigherBomb(opponentValue);
                
            default:
                return null;
        }
    }
    
    // -------------------- 辅助方法 --------------------
    
    /**
     * 对牌型字符串进行排序（按牌值降序）
     * @param cardSets 牌型字符串列表
     * @return 排序后的列表
     */
    private List<String> sortCardStrings(List<String> cardSets) {
        List<String> sorted = new ArrayList<>(cardSets);
        Collections.sort(sorted, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int value1 = CommonUtils.getCardSetValue(s1);
                int value2 = CommonUtils.getCardSetValue(s2);
                return Integer.compare(value2, value1); // 降序排序
            }
        });
        return sorted;
    }
    
    /**
     * 获取牌型列表中价值最高的组合
     * @param cardSets 牌型列表
     * @return 价值最高的牌型标识
     */
    private String getHighestCardSet(List<String> cardSets) {
        if (cardSets.isEmpty()) return null;
        return sortCardStrings(cardSets).get(0);
    }
    
    /**
     * 获取牌型列表中价值最低的组合
     * @param cardSets 牌型列表
     * @return 价值最低的牌型标识
     */
    private String getLowestCardSet(List<String> cardSets) {
        if (cardSets.isEmpty()) return null;
        List<String> sorted = sortCardStrings(cardSets);
        return sorted.get(sorted.size() - 1);
    }
    
    /**
     * 查找比指定牌值高的单张
     * @param targetValue 目标牌值
     * @return 更高牌值的单张，如果没有返回null
     */
    private String findHigherSingle(int targetValue) {
        for (String card : getSingles()) {
            if (CommonUtils.getCardValueFromString(card) > targetValue) {
                return card;
            }
        }
        return null;
    }
    
    /**
     * 查找比指定牌值高的对子
     * @param targetValue 目标牌值
     * @return 更高牌值的对子，如果没有返回null
     */
    private String findHigherPair(int targetValue) {
        for (String pair : getPairs()) {
            if (CommonUtils.getCardSetValue(pair) > targetValue) {
                return pair;
            }
        }
        return null;
    }
    
    /**
     * 查找比指定牌值高的三张
     * @param targetValue 目标牌值
     * @return 更高牌值的三张，如果没有返回null
     */
    private String findHigherThree(int targetValue) {
        for (String three : getThrees()) {
            if (CommonUtils.getCardSetValue(three) > targetValue) {
                return three;
            }
        }
        return null;
    }
    
    /**
     * 查找比指定顺子大的顺子
     * @param targetStraight 目标顺子
     * @return 更大的顺子，如果没有返回null
     */
    private String findHigherStraight(String targetStraight) {
        int targetLength = targetStraight.split(",").length;
        int targetStart = CommonUtils.getCardSetValue(targetStraight);
        
        for (String straight : getStraights()) {
            String[] cards = straight.split(",");
            if (cards.length == targetLength) {
                int startValue = CommonUtils.getCardValueFromString(cards[0]);
                if (startValue > targetStart) {
                    return straight;
                }
            }
        }
        return null;
    }
    
    /**
     * 查找比指定连对大的连对
     * @param targetConsecutivePair 目标连对
     * @return 更大的连对，如果没有返回null
     */
    private String findHigherConsecutivePairs(String targetConsecutivePair) {
        int targetPairs = targetConsecutivePair.split(",").length / 2;
        int targetStart = CommonUtils.getCardSetValue(targetConsecutivePair);
        
        for (String consecutivePair : getConsecutivePairs()) {
            String[] cards = consecutivePair.split(",");
            if (cards.length / 2 == targetPairs) {
                int startValue = CommonUtils.getCardValueFromString(cards[0]);
                if (startValue > targetStart) {
                    return consecutivePair;
                }
            }
        }
        return null;
    }
    
    /**
     * 查找比指定飞机大的飞机
     * @param targetAirplane 目标飞机
     * @return 更大的飞机，如果没有返回null
     */
    private String findHigherAirplane(String targetAirplane) {
        int targetGroups = targetAirplane.split(",").length / 3;
        int targetStart = CommonUtils.getCardSetValue(targetAirplane);
        
        for (String airplane : getAirplanes()) {
            String[] cards = airplane.split(",");
            if (cards.length / 3 == targetGroups) {
                int startValue = CommonUtils.getCardValueFromString(cards[0]);
                if (startValue > targetStart) {
                    return airplane;
                }
            }
        }
        return null;
    }
    
    /**
     * 查找比指定炸弹大的炸弹
     * @param targetValue 目标炸弹牌值
     * @return 更大的炸弹，如果没有返回null
     */
    private String findHigherBomb(int targetValue) {
        for (String bomb : getBombs()) {
            if (CommonUtils.getCardSetValue(bomb) > targetValue) {
                return bomb;
            }
        }
        return null;
    }
    
    /**
     * 获取所有牌型的字符串表示（用于调试）
     * @return 牌型描述字符串
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("GameModel:\n");
        
        if (!singles.isEmpty()) sb.append("  Singles: ").append(singles.size()).append("\n");
        if (!pairs.isEmpty()) sb.append("  Pairs: ").append(pairs.size()).append("\n");
        if (!threes.isEmpty()) sb.append("  Threes: ").append(threes.size()).append("\n");
        if (!straights.isEmpty()) sb.append("  Straights: ").append(straights.size()).append("\n");
        if (!consecutivePairs.isEmpty()) sb.append("  ConsecutivePairs: ").append(consecutivePairs.size()).append("\n");
        if (!airplanes.isEmpty()) sb.append("  Airplanes: ").append(airplanes.size()).append("\n");
        if (!bombs.isEmpty()) sb.append("  Bombs: ").append(bombs.size()).append("\n");
        
        sb.append("Total Weight: ").append(getTotalWeight());
        return sb.toString();
    }
} GameModl {
    
}
